﻿using System;
using System.Drawing;
using System.Windows.Forms;
using AForge.Video.VFW;


namespace AIthin.Controls
{
    class LearnStream
    {
        /// <summary>
        /// Squaresize ex. 16x16 Size=16
        /// </summary>
        public int Size { get; protected set; }
        /// <summary>
        /// oeffnet neues Instanz vom AVI Datei
        /// </summary>
        AVIReader reader = null;
        /// <summary>
        /// Bitmap die abbildet Reality in den Zeitschritt
        /// </summary>
        public Bitmap currentBitmap { get; protected set; }
        /// <summary>
        /// Bitmap die Abbildet InputSignale
        /// </summary>
        public Bitmap inputBitmap { get; protected set; }
        /// <summary>
        /// Bitmap die Abbildet Output Signale
        /// </summary>
        public Bitmap outputBitmap { get; protected set; }
        /// <summary>
        /// number of frames to earn
        /// </summary>
        public int LearnSets { get; protected set; }
        /// <summary>
        /// Anzal Output Signals wird von der erste Zeile Output genommen
        /// wieviel punkten sind Weiss so viel Output Signals sind da.
        /// </summary>
        public int OutputsCount { get; protected set; }
        /// <summary>
        /// network error
        /// </summary>

        public LearnStream()
        {
            reader = new AVIReader();

            Size = 64;

            currentBitmap = new Bitmap(2 * Size, Size, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            inputBitmap = new Bitmap(Size, Size, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            outputBitmap = new Bitmap(Size, Size, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
        }
        public bool GetLearnSet(String FileName, out short[][] input, out short[][] output)
        {
            //open file
            try
            {
                reader.Open(FileName);
            }
            catch (Exception)
            {
                MessageBox.Show("Error read learn File.");
                input = null;
                output = null;
                return false;
            }
            //get Learnsets count
            LearnSets = reader.Length;
            Size = reader.Height;

            currentBitmap = new Bitmap(2 * Size, Size, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            inputBitmap = new Bitmap(Size, Size, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            outputBitmap = new Bitmap(Size, Size, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

            short[][] Input = new short[LearnSets][];
            short[][] Output = new short[LearnSets][];

            GetOutputsCount();

            for (int i = 0; i < LearnSets; i++)
            {
                Input[i] = new short[Size * Size];
                Output[i] = new short[OutputsCount];
            }

            int Epoch;
            while ((Epoch = reader.Position) < reader.Length)
            {
                currentBitmap = reader.GetNextFrame();

                SetInput(Epoch, ref Input);
                SetOutput(Epoch, ref Output);

            }
            reader.Close();

            input = Input;
            output = Output;
            return true;
        }
        /// <summary>
        /// get full learnset from AVI 
        /// </summary>
        /// <param name="FileName"></param>
        /// <param name="input">input data as a matrix [learnset number][x,y]</param>
        /// <param name="output">output data as a vector [learnset number][x,y]</param>
        /// <returns></returns>
        public bool GetLearnSet(String FileName, out short[][,] input, out short[][] output)
        {
            //open file
            try
            {
                reader.Open(FileName);
            }
            catch (Exception)
            {
                MessageBox.Show("Error read learn File.");
                input = null;
                output = null;
                return false;
            }
            //get Learnsets count
            LearnSets = reader.Length;
            Size = reader.Height;

            currentBitmap = new Bitmap(2 * Size, Size, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            inputBitmap = new Bitmap(Size, Size, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            outputBitmap = new Bitmap(Size, Size, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

            short[][,] Input = new short[LearnSets][,];
            short[][] Output = new short[LearnSets][];

            GetOutputsCount();

            for (int i = 0; i < LearnSets; i++)
            {
                Input[i] = new short[Size, Size];
                Output[i] = new short[OutputsCount];
            }

            int Epoch;
            while ((Epoch = reader.Position) < reader.Length)
            {
                currentBitmap = reader.GetNextFrame();

                SetInput(Epoch, ref Input);
                SetOutput(Epoch, ref Output);

            }
            reader.Close();

            input = Input;
            output = Output;
            return true;
        }
        public bool open(String FileName)
        {
            //open file
            try
            {
                reader.Open(FileName);
            }
            catch (Exception)
            {
                MessageBox.Show("Error read learn File.");
                return false;
            }
            //get Learnsets count
            LearnSets = reader.Length;
            Size = reader.Height;

            currentBitmap = new Bitmap(2 * Size, Size, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            inputBitmap = new Bitmap(Size, Size, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            outputBitmap = new Bitmap(Size, Size, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

            return true;
        }
        public short[,] getNextFrame()
        {

            short[,] Input = new short[Size, Size];

            if (reader.Position < reader.Length)
            {
                currentBitmap = reader.GetNextFrame();
                SetInput(ref Input);
            }
            else
                reader.Close();

            return Input;
        }
        public Bitmap getNextFrame(int i)
        {

             if (reader.Position < reader.Length)
            {
                currentBitmap = reader.GetNextFrame();
            }
            else
                reader.Close();

             return currentBitmap;
        }
        private void GetOutputsCount()
        {
            currentBitmap = reader.GetNextFrame();

            OutputsCount = 0;
            for (int i = 0; i < Size; i++)
                // if pixel is white
                if (ColorToShort(currentBitmap.GetPixel(Size + i, 0)) > 0) OutputsCount++;
            // at start
            reader.Position = 0;

        }
        private void DrawOutput(int LearnSetNummer, ref short[][] Output)
        {
            int[] OutputColor = new int[OutputsCount];
            for (int i = 0; i < OutputsCount; i++)
            {
                OutputColor[i] = System.Convert.ToInt16(Math.Abs(Output[LearnSetNummer][i] * 255));
                for (int k = 0; k < Size; k++)
                    outputBitmap.SetPixel(k, i + 1, Color.FromArgb(OutputColor[i], OutputColor[i], OutputColor[i]));
            }
        }
        private void DrawInput(int LearnSetNummer, ref short[][] Input)
        {
            int m = 0;
            for (int j = 0; j < Size; j++)
                for (int i = 0; i < Size; i++)
                {
                    if (Input[LearnSetNummer][m++] > 0)
                        inputBitmap.SetPixel(j, i, Color.White);
                    else
                        inputBitmap.SetPixel(j, i, Color.Black);
                }
        }
        private void SetInput(int LearnSetNummer, ref short[][] Input)
        {
            int Index = 0;
            for (int i = 0; i < Size; i++)
                for (int j = 0; j < Size; j++)
                    // !!! black is 1
                    Input[LearnSetNummer][Index++] = Convert.ToInt16((ColorToShort(currentBitmap.GetPixel(i, j)) > 0) ? 0 : 1);
        }
        private void SetInput(int LearnSetNummer, ref short[][,] Input)
        {
            for (int i = 0; i < Size; i++)
                for (int j = 0; j < Size; j++)
                    // !!! black is 1
                    Input[LearnSetNummer][i, j] = Convert.ToInt16((ColorToShort(currentBitmap.GetPixel(i, j)) > 0) ? 0 : 1);
        }
        private void SetInput(ref short[,] Input)
        {
            for (int i = 0; i < Size; i++)
                for (int j = 0; j < Size; j++)
                    // !!! black is 1
                    Input[i, j] = Convert.ToInt16((ColorToShort(currentBitmap.GetPixel(i, j)) > 0) ? 0 : 1);
        }
        private void SetOutput(int LearnSetNummer, ref short[][] Output)
        {
            for (int i = 0; i < OutputsCount; i++)
                // !!! black is 1
                Output[LearnSetNummer][i] = Convert.ToInt16((ColorToShort(currentBitmap.GetPixel(Size, i + 1)) > 0) ? 0 : 1);
        }
        private short ColorToShort(Color inColor)
        {
            return Convert.ToInt16((inColor.R + inColor.G + inColor.B) / 3.0f);
        }
        public void SetInput(Bitmap bm, ref short[][] Input)
        {
            int Width = bm.Width / 2;
            int Height = bm.Height;
            for (int i = 0; i < Width; i++)
                for (int j = 0; j < Height; j++)
                    // !!! black is 1
                    Input[i][j] = Convert.ToInt16((ColorToShort(bm.GetPixel(i, j)) > 0) ? 0 : 1);
        }
    }
}
